#include "socket.h"
#include "netinet/tcp.h"

#if 0
int main()
{
        int s_fd;
        int c_fd;
        char readbuf[128] = {0};
        char *mes = "welcome to you!";

        struct sockaddr_in s_addr;              // about serve in "bind"
        struct sockaddr_in c_addr;              // about client in "accept"

        memset(&s_addr,0,sizeof(struct sockaddr_in));
        memset(&c_addr,0,sizeof(struct sockaddr_in));

        //1.socket
        s_fd = socket(AF_INET,SOCK_STREAM,0);
        if(s_fd == -1){
                printf("socket error\n");
                exit(-1);
        }

        //int bind(int sockfd, const struct sockaddr *addr,
        //        socklen_t addrlen);
        s_addr.sin_family = AF_INET;                             //Internet
        s_addr.sin_port = htons(8989);                           //port
        inet_aton("10.164.125.59",&s_addr.sin_addr);             //address

        //2.bind
        bind(s_fd,(struct sockaddr*)&s_addr,sizeof(struct sockaddr_in));

        //3.listen
        listen(s_fd,10);

        //4.accept
        int c_addrlen = sizeof(struct sockaddr_in);
        c_fd = accept(s_fd,(struct sockaddr*)&c_addr,&c_addrlen);
        if(c_fd == -1){
                perror("accept");
        }
        printf("get connect:%s\n",inet_ntoa(c_addr.sin_addr));

        int n_read = read(c_fd,readbuf,128);
        if(n_read == -1){
                perror("read");
        }else {
                printf("get message from client: %d %s\n",n_read,readbuf);
        }

        int n_write =  write(c_fd,mes,strlen(mes));
        if(n_write == -1){
                perror("write");
        }else{
                printf("write %d byte ok\n",n_write);
        }

        return 0;
}
#endif

int socket_init()
{
    int s_fd;
    int ret;
    // int c_fd;
    struct sockaddr_in s_addr; // about serve in "bind"
    // struct sockaddr_in c_addr;              // about client in "accept"

    memset(&s_addr, 0, sizeof(struct sockaddr_in));

    // 1.socket
    s_fd = socket(AF_INET, SOCK_STREAM, 0);
    if (s_fd == -1)
    {
        printf("socket error\n");
        exit(-1);
    }

    // int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
    s_addr.sin_family = AF_INET;          // Internet
    s_addr.sin_port = htons(SOCKET_PORT); // port
    // 把字符串形式地址转换成网络能识别的形式
    inet_aton(SOCKET_ADDRESS, &s_addr.sin_addr); // address

    // 2.bind
    bind(s_fd, (struct sockaddr *)&s_addr, sizeof(struct sockaddr_in));

    // 3.listen
    ret = listen(s_fd, 1);
    if (-1 == ret)
    {
        fprintf(stderr, "error listen\n");
        return -1;
    }

    return s_fd;
}

// 心跳包机制
int set_keepalive(int sockfd, int keepalive_idle, int keepalive_interval, int keepalive_count)
{
    int optval = 1;
    int optlen = sizeof(optval);

    // 启用keepalive
    if (setsockopt(sockfd, SOL_SOCKET, SO_KEEPALIVE, &optval, optlen) < 0)
    {
        perror("setsockopt (SO_KEEPALIVE)");
        return -1;
    }

    // 在没有数据交换的keepalive_idle秒后开始发送探测包
    if (setsockopt(sockfd, SOL_TCP, TCP_KEEPIDLE, (void *)&keepalive_idle, sizeof(keepalive_idle)) < 0)
    {
        perror("setsockopt (TCP_KEEPIDLE)");
    }
    // 探测包之间的间隔
    if (setsockopt(sockfd, SOL_TCP, TCP_KEEPINTVL, (void *)&keepalive_interval, sizeof(keepalive_interval)) < 0)
    {
        perror("setsockopt (TCP_KEEPINTVL)");
    }
    // 探测次数，在探测失败多少次后关闭连接
    if (setsockopt(sockfd, SOL_TCP, TCP_KEEPCNT, (void *)&keepalive_count, sizeof(keepalive_count)) < 0)
    {
        perror("setsockopt (TCP_KEEPCNT)");
    }

    return 0;
}
